module decode_unit(/*AUTOARG*/
   // Outputs
   regA_o_dataA, regA_o_dataB, regB_o_dataA, regB_o_dataB,
   regA_o_immediate, regB_o_immediate, regA_o_tag, regB_o_tag,
   regA_o_dst_reg, regB_o_dst_reg, regA_o_ctrl_signals,
   regA_mem_o_valid, regB_o_ctrl_signals, regB_mem_o_valid,
   // Inputs
   clk, reset, regA_i_inst, regA_i_tag, regA_i_haz, regB_i_inst,
   regB_i_tag, regB_i_haz, wbA_i_addr, wbA_i_data, wbA_i_ctrl,
   wbB_i_addr, wbB_i_data, wbB_i_ctrl
   );


input clk,reset;
input [31:0] regA_i_inst;
input [3:0] regA_i_tag;
input regA_i_haz;
input [31:0] regB_i_inst;
input [3:0] regB_i_tag;
input regB_i_haz;

input [4:0] wbA_i_addr;
input [31:0] wbA_i_data;
input wbA_i_ctrl;
input [4:0] wbB_i_addr;
input [31:0] wbB_i_data;
input wbB_i_ctrl;    

output [31:0] regA_o_dataA;
output [31:0] regA_o_dataB;
output [31:0] regB_o_dataA;
output [31:0] regB_o_dataB;
output [31:0] regA_o_immediate;
output [31:0] regB_o_immediate;
output [3:0] regA_o_tag;
output [3:0] regB_o_tag;
output [4:0] regA_o_dst_reg;
output [4:0] regB_o_dst_reg;

output [5:0] regA_o_ctrl_signals;
output [3:0] regA_mem_o_valid;

output [5:0] regB_o_ctrl_signals;
output [3:0] regB_mem_o_valid;

wire [31:0] regA_b_dataA_w;
wire [31:0] regA_b_dataB_w;
wire [31:0] regB_b_dataA_w;
wire [31:0] regB_b_dataB_w;

wire [5:0] regA_b_ctrl_signals_w;
wire [3:0] regA_mem_b_valid_w;
wire [5:0] regB_b_ctrl_signals_w;
wire [3:0] regB_mem_b_valid_w;

reg [31:0] regA_b_dataA;
reg [31:0] regA_b_dataB;
reg [31:0] regB_b_dataA;
reg [31:0] regB_b_dataB;

reg [31:0] regA_b_immediate;
reg [31:0] regB_b_immediate;
reg [3:0] regA_b_tag;
reg [3:0] regB_b_tag;
reg [4:0] regA_b_dst_reg;
reg [4:0] regB_b_dst_reg;

reg [5:0] regA_b_ctrl_signals;
reg [3:0] regA_mem_b_valid;
reg [5:0] regB_b_ctrl_signals;
reg [3:0] regB_mem_b_valid;


assign regA_o_dataA = regA_b_dataA;
assign regA_o_dataB = regA_b_dataB;
assign regB_o_dataA = regB_b_dataA;
assign regB_o_dataB = regB_b_dataB;
assign regA_o_immediate = regA_b_immediate;
assign regB_o_immediate = regB_b_immediate;
assign regA_o_tag = regA_b_tag;
assign regB_o_tag = regB_b_tag;
assign regA_o_dst_reg = regA_b_dst_reg;
assign regB_o_dst_reg = regB_b_dst_reg;

assign regA_mem_o_valid = regA_mem_b_valid;
assign regA_o_ctrl_signals = regA_b_ctrl_signals;
assign regB_mem_o_valid = regB_mem_b_valid;
assign regB_o_ctrl_signals = regB_b_ctrl_signals;

regfile_and_decoder registerfile( 
	// Outputs
   .read_data1(regA_b_dataA_w), .read_data2(regA_b_dataB_w), .read_data3(regB_b_dataA_w), .read_data4(regB_b_dataB_w),
  	// Inputs
   .clk(clk), .reset(reset), .regwrite1(wbA_i_ctrl), .regwrite2(wbB_i_ctrl), .write1_addr(wbA_i_addr), .write2_addr(wbB_i_addr),
   .read_data1_addr(regA_i_inst[25:21]), .read_data2_addr(regA_i_inst[20:16]), .read_data3_addr(regB_i_inst[25:21]), .read_data4_addr(regB_i_inst[20:16]),
   .write_data1(wbA_i_data), .write_data2(wbB_i_data)
   );

control ctrlA(
   // Outputs
   .ctrl_o_signals(regA_b_ctrl_signals_w), .ctrl_mem_o_valid(regA_mem_b_valid_w),
   // Inputs
   .clk(clk), .reset(reset), .ctrl_i_opcode(regA_i_inst[31:26]), .ctrl_i_funct(regA_i_inst[5:0])
   );


control ctrlB(
   // Outputs
   .ctrl_o_signals(regB_b_ctrl_signals_w), .ctrl_mem_o_valid(regB_mem_b_valid_w),
   // Inputs
   .clk(clk), .reset(reset), .ctrl_i_opcode(regB_i_inst[31:26]), .ctrl_i_funct(regB_i_inst[5:0])
   );

always @(posedge clk or negedge reset or posedge regA_i_inst[15] or posedge regB_i_inst[15] or posedge regA_i_haz)
begin
	if(!reset)
		begin
		regA_b_dataA = 0;
		regA_b_dataB = 0;
		regB_b_dataA = 0;
		regB_b_dataB = 0;
		regA_b_immediate = 0;
		regB_b_immediate =0;
		regA_b_tag = 0;
		regB_b_tag = 0;
		//regA_b_dst_reg = 0;
		//regB_b_dst_reg = 0;
		end
	else
	 if(regA_i_haz)
		begin
		regA_b_tag = regA_i_tag;
		regB_b_tag = regB_i_tag;
		
		if(regA_i_inst[15])
			regA_b_immediate[31:16] = 16'b1111111111111111;
		else
			regA_b_immediate[31:16] = 16'b0;
		
		if(regB_i_inst[15])
			regB_b_immediate[31:16] = 16'b1111111111111111;
		else
			regB_b_immediate[31:16] = 16'b0;

		regA_b_immediate[15:0] <= regA_i_inst[15:0];
		regB_b_immediate[15:0] <= regB_i_inst[15:0];

		
		regA_b_dataA = regA_b_dataA_w;
		regA_b_dataB = regA_b_dataB_w;
		regB_b_dataA = regB_b_dataA_w;
		regB_b_dataB = regB_b_dataB_w;
		
		

		//----control-----

		regA_b_ctrl_signals = regA_b_ctrl_signals_w;
		regA_mem_b_valid = regA_mem_b_valid_w;
		regB_b_ctrl_signals = regB_b_ctrl_signals_w;
		regB_mem_b_valid = regB_mem_b_valid_w;
		
		end
end

always @ (regA_i_inst[31:26] or regB_i_inst[31:26] or regA_i_haz)
begin
if(regA_i_haz)
begin
	if(!regA_i_inst[31:26])
		regA_b_dst_reg = regA_i_inst[15:11];
	else 
		regA_b_dst_reg = regA_i_inst[20:16];
		
	if(!regB_i_inst[31:26])
		regB_b_dst_reg = regB_i_inst[15:11];
	else 
		regB_b_dst_reg = regB_i_inst[20:16];
		
end
end

endmodule
